package gat.application.backgroundUser.impl;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.UpdateWrapper;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.bitsun.core.common.exception.AppException;
import com.bitsun.core.common.exception.ErrorCode;
import com.bitsun.core.common.persistence.BasePService;
import com.bitsun.core.common.persistence.IPService;
import com.bitsun.core.common.persistence.Pager;
import com.bitsun.core.common.persistence.QueryParamUtils;
import com.google.common.base.CaseFormat;
import gat.application.backgroundUser.RoleService;
import gat.application.backgroundUser.UserRoleService;
import gat.convertor.backgroundUser.UserRoleReqDtoConvertor;
import gat.convertor.backgroundUser.UserRoleResDtoConvertor;
import gat.dto.req.backgroundUser.BackgroundUserBaseParams;
import gat.dto.req.backgroundUser.BackgroundUserParamsDto;
import gat.dto.req.backgroundUser.UserRoleReqDto;
import gat.dto.res.backgroundUser.RoleResDto;
import gat.dto.res.backgroundUser.UserRoleResDto;
import gat.infrastructure.persistence.dao.backgroundUser.UserRoleMapper;
import gat.infrastructure.persistence.po.backgroundUser.UserRolePo;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.collections.CollectionUtils;
import org.apache.commons.lang3.math.NumberUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.beans.PropertyDescriptor;
import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.lang.reflect.Modifier;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

/**
 * 示例表，应用（业务编排）层实现
 * @author: tmac
 * @email: tmac
 */
@Slf4j
@Service("userRoleAppService")
@Transactional(rollbackFor = Exception.class)
public class UserRoleServiceImpl implements UserRoleService {

    @Autowired
    private UserRoleReqDtoConvertor userRoleReqDtoConvertor;

    @Autowired
    private UserRoleResDtoConvertor userRoleResDtoConvertor;

    @Autowired
    private RoleService roleService;


    private IPService<UserRolePo> userRolePoService;

    @SuppressWarnings("SpringJavaAutowiringInspection")
    public UserRoleServiceImpl(UserRoleMapper userRoleMapper) {
        this.userRolePoService = new BasePService(userRoleMapper);
    }


    @Override
    public List<UserRoleResDto> selectByRoleId(Long roleId, Long userId) {
        QueryWrapper<UserRolePo> queryWrapper = new QueryWrapper<>();
        queryWrapper.lambda().eq(UserRolePo::getRoleId,roleId);
        queryWrapper.lambda().ne(UserRolePo::getUserId,userId);
        List<UserRolePo> list = userRolePoService.list(queryWrapper);
        List<UserRoleResDto> resDtos = userRoleResDtoConvertor.poList2DtoList(list);
        return resDtos;
    }

    @Override
    public UserRoleResDto save(UserRoleReqDto reqDto) {
        UserRolePo po = userRoleReqDtoConvertor.dto2Po(reqDto);
        userRolePoService.save(po);
        UserRoleResDto resDto = userRoleResDtoConvertor.po2Dto(po);
        return resDto;
    }

    @Override
    public boolean save(BackgroundUserBaseParams params) {
        List<Long>  list = params.getRoleIds();
        List<UserRolePo>  poList = new ArrayList<>();
        for (Long roleId : list){
            UserRolePo userRolePo = new UserRolePo();
            userRolePo.setRoleId(roleId);
            userRolePo.setUserId(Long.valueOf(params.getUserCode()));
            poList.add(userRolePo);
        }
        return  userRolePoService.saveBatch(poList);

    }

    @Override
    public boolean deleteByIds(String ids) {
        try {
            List<Long> idLongList =
            Arrays.asList(ids.split(",")).stream().map(s -> NumberUtils.createLong(s.trim())).collect(Collectors.toList());
            return userRolePoService.removeByIds(idLongList);
        } catch (Exception e) {
            throw new AppException("参数错误：" + ids, ErrorCode.pc("417"), e);
        }
     }

    @Override
    public Pager<UserRoleResDto> doPager(Map<String, Object> params) {
        Pager<UserRolePo> poPager = userRolePoService.queryPage(params, UserRolePo.class);
        Pager<UserRoleResDto> resDtoPager = userRoleResDtoConvertor.convertPoPager2ResDtoPager(poPager);
        return resDtoPager;
    }

    @Override
    public UserRoleResDto selectOne(Long id) {
        UserRolePo po = userRolePoService.getById(id);
        UserRoleResDto resDto = userRoleResDtoConvertor.po2Dto(po);
        return resDto;
    }

    @Override
    public UserRoleResDto selectOne(Map<String, Object> params) {
        QueryWrapper queryWrapper = QueryParamUtils.queryWrapper4eq(UserRolePo::new, params);
        queryWrapper.last(" limit 1");
        UserRolePo po = userRolePoService.getOne(queryWrapper);
        UserRoleResDto resDto = userRoleResDtoConvertor.po2Dto(po);
        return resDto;
    }

    @Override
    public boolean updateProps(Long id, Map<String, Object> params) {
        UpdateWrapper<UserRolePo> updateWrapper = QueryParamUtils.updateWrapper4Map(UserRolePo::new, id, params);
        return userRolePoService.update(new UserRolePo(), updateWrapper);
        }

    @Override
    public boolean updateProps(Long id, UserRoleReqDto reqDto) {
        UserRolePo po = userRoleReqDtoConvertor.dto2Po(reqDto);
        po.setId(id);
        return userRolePoService.updateById(po);
    }


    @Override
    public boolean updateAllProps(Long id, UserRoleReqDto reqDto) {
        UpdateWrapper<UserRolePo> updateWrapper = Wrappers.update();
        updateWrapper.eq("id", id);
        Field[] fields = UserRoleReqDto.class.getDeclaredFields();
        Arrays.stream(fields).filter(f -> !Modifier.isStatic(f.getModifiers())).forEach(field -> {
        try {
        PropertyDescriptor propertyDescriptor = new PropertyDescriptor(field.getName(), UserRoleReqDto.class);
        Method getMethod = propertyDescriptor.getReadMethod();
        String fileNameCamel = getMethod.getName().substring(3);
        String fileNameUnderline = CaseFormat.LOWER_CAMEL.to(CaseFormat.LOWER_UNDERSCORE, fileNameCamel);
        updateWrapper.set(fileNameUnderline, getMethod.invoke(reqDto));
        } catch (Exception ex) {
        log.warn("属性不存在get方法："+field.getName(),ex);
        }
        });
        return userRolePoService.update(new UserRolePo(), updateWrapper);
    }

    @Override
    public Boolean updateByUserId(UserRoleReqDto role) {
        UpdateWrapper<UserRolePo> updateWrapper = new UpdateWrapper<>();
        updateWrapper.set("role_id",role.getRoleId());
        updateWrapper.eq("user_id",role.getUserId());
        return  userRolePoService.update(updateWrapper);
    }

    @Override
    public UserRolePo getOne(UserRoleReqDto role) {

       UserRolePo  userRolePo =  userRolePoService.getOne(new QueryWrapper<UserRolePo>().lambda()
                .eq(UserRolePo::getUserId, role.getUserId())
                .eq(UserRolePo::getRoleId,role.getRoleId()))
                ;
        return userRolePo;
    }



    @Override
    public boolean updateUserRole(BackgroundUserParamsDto params) {

        userRolePoService.remove(new QueryWrapper<UserRolePo>().lambda()
                .eq(UserRolePo::getUserId, Long.valueOf(params.getId()))
                .in(UserRolePo::getRoleId, params.getOldRoleIds()));
        List<UserRolePo> list = new ArrayList<>();
        params.getNewRoleIds().forEach(i -> {
            UserRolePo userRolePo = new UserRolePo();
            userRolePo.setUserId(Long.valueOf(params.getId()));
            userRolePo.setRoleId(i);
            list.add(userRolePo);
        });

        return   userRolePoService.saveBatch(list);

    }

    @Override
    public List<UserRoleResDto> getByRoleId(Long id) {
        QueryWrapper<UserRolePo> queryWrapper = new QueryWrapper<>();
        queryWrapper.lambda().eq(UserRolePo::getRoleId,id);
        List<UserRolePo> list = userRolePoService.list(queryWrapper);
        List<UserRoleResDto> resDtos = userRoleResDtoConvertor.poList2DtoList(list);
        return resDtos;
    }

    @Override
    public List<RoleResDto> getUserRoleById(Long id) {
        List<UserRolePo> userRolePos = userRolePoService.list(new LambdaQueryWrapper<UserRolePo>()
                .eq(UserRolePo::getUserId,id));
        if (CollectionUtils.isNotEmpty(userRolePos)){
            List<Long> roleIds = userRolePos.stream().map(UserRolePo::getRoleId).collect(Collectors.toList());
           return roleService.getByRoleIds(roleIds);
        }else{
            return new ArrayList<>();
        }
    }


    @Override
    public List<Long> selByUserId(Long userId) {
        QueryWrapper<UserRolePo> queryWrapper = new QueryWrapper<>();
        queryWrapper.lambda().eq(UserRolePo::getUserId, userId);
        List<UserRolePo> list = userRolePoService.list(queryWrapper);
        List<Long> collect = list.stream().map(UserRolePo::getRoleId).collect(Collectors.toList());
        return collect;
    }

}